package main

import (
	"fmt"
	"reflect"
)

type MyInt int64

//reflect 包
func reflectType(x interface{}) {
	t := reflect.TypeOf(x)
	v := reflect.ValueOf(x)	//v也可以获取type kind
	fmt.Printf("type: %v, kind : %v, value: %v\n", t.Name(), t.Kind(), v) //kind是指的底层类型
}
func main() {
	var a float32 = 3.14
	reflectType(a)
	var num int8 = 100
	reflectType(num)
	var myint MyInt
	myint = 100
	reflectType(myint)
	reflectSetValue(&myint)
	reflectType(myint)
	var m map[string]int
	m = map[string]int{"name" : 1}
	reflectType(m)	//map 数组 切片 指针类型的name 都是空
	stu1 := Student{
		Name: "小王子",
		Score: 90,
	}
	reflectStruct(stu1)
	PrintMethod(stu1)
}

func PrintMethod(x interface{})  {
	t := reflect.TypeOf(x)
	v := reflect.ValueOf(x)
	fmt.Println(t.NumMethod())
	for i := 0; i < v.NumMethod(); i++ {
		methodType := v.Method(i).Type()
		fmt.Printf("method name:%s\n", t.Method(i).Name)
		fmt.Printf("method:%s\n", methodType)
		// 通过反射调用方法传递的参数必须是 []reflect.Value 类型
		var args []reflect.Value
		v.Method(i).Call(args)
	}
}

func (s Student) Sleep() string {
	msg := "good sleep"
	fmt.Println(msg)
	return msg
}

// Study 给student添加两个方法 Study和Sleep(注意首字母大写)
func (s Student) Study() string {
	msg := "good good study"
	fmt.Println(msg)
	return msg
}

type Student struct {
	Name string `json:"name"`
	Score int `json:"score"`
}

func reflectStruct(x interface{}) {
	v := reflect.TypeOf(x)
	for i := 0; i < v.NumField(); i++ {
		field := v.Field(i)
		fmt.Printf("name:%s index:%d type:%v json tag:%v\n", field.Name, field.Index, field.Type, field.Tag.Get("json"))
	}
	if scoreField, ok := v.FieldByName("Score"); ok {
		fmt.Printf("name:%s index:%d type:%v json tag:%v\n", scoreField.Name, scoreField.Index, scoreField.Type, scoreField.Tag.Get("json"))
	}
}

func reflectSetValue(x interface{}) {
	v := reflect.ValueOf(x)
	//if v.Kind() == reflect.Int64 {	//修改的是副本，reflect会引发panic
	//	v.SetInt(400)
	//}
	//只有elem获取指针对应的值
	if v.Elem().Kind() == reflect.Int64 {
		v.Elem().SetInt(400)
	}
}
